/* src/interfaces/ecpg/compatlib/informix.c */

#define POSTGRES_ECPG_INTERNAL
#include "postgres_fe.h"

#include <math.h>
#include <ctype.h>
#include <limits.h>

#include "ecpg_informix.h"
#include "ecpgerrno.h"
#include "ecpgtype.h"
#include "pgtypes_date.h"
#include "pgtypes_error.h"
#include "pgtypes_numeric.h"
#include "sqlca.h"
#include "sqltypes.h"

/* 这在ecpglib/misc.c中也被定义，通过定义两次我们不必导出符号 */

static struct sqlca_t sqlca_init =
{
	{
		'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '
	},
	sizeof(struct sqlca_t),
	0,
	{
		0,
		{
			0
		}
	},
	{
		'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '
	},
	{
		0, 0, 0, 0, 0, 0
	},
	{
		0, 0, 0, 0, 0, 0, 0, 0
	},
	{
		'0', '0', '0', '0', '0'
	}
};
static int fc_deccall2(decimal *fc_arg1, decimal *fc_arg2, int (*fc_ptr) (numeric *, numeric *))
{
	numeric    *fc_a1,
			   *fc_a2;
	int			fc_i;

	if ((fc_a1 = PGTYPESnumeric_new()) == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	if ((fc_a2 = PGTYPESnumeric_new()) == NULL)
	{
		PGTYPESnumeric_free(fc_a1);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	if (PGTYPESnumeric_from_decimal(fc_arg1, fc_a1) != 0)
	{
		PGTYPESnumeric_free(fc_a1);
		PGTYPESnumeric_free(fc_a2);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	if (PGTYPESnumeric_from_decimal(fc_arg2, fc_a2) != 0)
	{
		PGTYPESnumeric_free(fc_a1);
		PGTYPESnumeric_free(fc_a2);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	fc_i = (*fc_ptr) (fc_a1, fc_a2);

	PGTYPESnumeric_free(fc_a1);
	PGTYPESnumeric_free(fc_a2);

	return fc_i;
}

static int fc_deccall3(decimal *fc_arg1, decimal *fc_arg2, decimal *fc_result, int (*fc_ptr) (numeric *, numeric *, numeric *))
{
	numeric    *fc_a1,
			   *fc_a2,
			   *fc_nres;
	int			fc_i;

	/*
	 * 我们在这里绝不能将结果设为NULL，因为它可能与其中一个参数是同一个变量
	 */
	if (risnull(CDECIMALTYPE, (char *) fc_arg1) || risnull(CDECIMALTYPE, (char *) fc_arg2))
		return 0;

	if ((fc_a1 = PGTYPESnumeric_new()) == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	if ((fc_a2 = PGTYPESnumeric_new()) == NULL)
	{
		PGTYPESnumeric_free(fc_a1);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	if ((fc_nres = PGTYPESnumeric_new()) == NULL)
	{
		PGTYPESnumeric_free(fc_a1);
		PGTYPESnumeric_free(fc_a2);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	if (PGTYPESnumeric_from_decimal(fc_arg1, fc_a1) != 0)
	{
		PGTYPESnumeric_free(fc_a1);
		PGTYPESnumeric_free(fc_a2);
		PGTYPESnumeric_free(fc_nres);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	if (PGTYPESnumeric_from_decimal(fc_arg2, fc_a2) != 0)
	{
		PGTYPESnumeric_free(fc_a1);
		PGTYPESnumeric_free(fc_a2);
		PGTYPESnumeric_free(fc_nres);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	fc_i = (*fc_ptr) (fc_a1, fc_a2, fc_nres);

	if (fc_i == 0)					/* 没有错误 */
	{

		/* 在后续出错时将结果设置为null */
		rsetnull(CDECIMALTYPE, (char *) fc_result);
		PGTYPESnumeric_to_decimal(fc_nres, fc_result);
	}

	PGTYPESnumeric_free(fc_nres);
	PGTYPESnumeric_free(fc_a1);
	PGTYPESnumeric_free(fc_a2);

	return fc_i;
}

/* 我们从数字函数开始 */
int decadd(decimal *fc_arg1, decimal *fc_arg2, decimal *fc_sum)
{
	errno = 0;
	fc_deccall3(fc_arg1, fc_arg2, fc_sum, PGTYPESnumeric_add);

	if (errno == PGTYPES_NUM_OVERFLOW)
		return ECPG_INFORMIX_NUM_OVERFLOW;
	else if (errno == PGTYPES_NUM_UNDERFLOW)
		return ECPG_INFORMIX_NUM_UNDERFLOW;
	else if (errno != 0)
		return -1;
	else
		return 0;
}

int deccmp(decimal *fc_arg1, decimal *fc_arg2)
{
	return fc_deccall2(fc_arg1, fc_arg2, PGTYPESnumeric_cmp);
}

void deccopy(decimal *fc_src, decimal *fc_target)
{
	memcpy(fc_target, fc_src, sizeof(decimal));
}

static char * fc_ecpg_strndup(const char *fc_str, size_t fc_len)
{
	size_t		fc_real_len = strlen(fc_str);
	int			fc_use_len = (int) ((fc_real_len > fc_len) ? fc_len : fc_real_len);

	char	   *fc_new = malloc(fc_use_len + 1);

	if (fc_new)
	{
		memcpy(fc_new, fc_str, fc_use_len);
		fc_new[fc_use_len] = '\0';
	}
	else
		errno = ENOMEM;

	return fc_new;
}

int deccvasc(const char *fc_cp, int fc_len, decimal *fc_np)
{
	char	   *fc_str;
	int			fc_ret = 0;
	numeric    *fc_result;

	rsetnull(CDECIMALTYPE, (char *) fc_np);
	if (risnull(CSTRINGTYPE, fc_cp))
		return 0;

	fc_str = fc_ecpg_strndup(fc_cp, fc_len);	/* decimal_in始终转换完整的字符串 */
	if (!fc_str)
		fc_ret = ECPG_INFORMIX_NUM_UNDERFLOW;
	else
	{
		errno = 0;
		fc_result = PGTYPESnumeric_from_asc(fc_str, NULL);
		if (!fc_result)
		{
			switch (errno)
			{
				case PGTYPES_NUM_OVERFLOW:
					fc_ret = ECPG_INFORMIX_NUM_OVERFLOW;
					break;
				case PGTYPES_NUM_BAD_NUMERIC:
					fc_ret = ECPG_INFORMIX_BAD_NUMERIC;
					break;
				default:
					fc_ret = ECPG_INFORMIX_BAD_EXPONENT;
					break;
			}
		}
		else
		{
			int			fc_i = PGTYPESnumeric_to_decimal(fc_result, fc_np);

			PGTYPESnumeric_free(fc_result);
			if (fc_i != 0)
				fc_ret = ECPG_INFORMIX_NUM_OVERFLOW;
		}
	}

	free(fc_str);
	return fc_ret;
}

int deccvdbl(double fc_dbl, decimal *fc_np)
{
	numeric    *fc_nres;
	int			fc_result = 1;

	rsetnull(CDECIMALTYPE, (char *) fc_np);
	if (risnull(CDOUBLETYPE, (char *) &fc_dbl))
		return 0;

	fc_nres = PGTYPESnumeric_new();
	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	fc_result = PGTYPESnumeric_from_double(fc_dbl, fc_nres);
	if (fc_result == 0)
		fc_result = PGTYPESnumeric_to_decimal(fc_nres, fc_np);

	PGTYPESnumeric_free(fc_nres);
	return fc_result;
}

int deccvint(int fc_in, decimal *fc_np)
{
	numeric    *fc_nres;
	int			fc_result = 1;

	rsetnull(CDECIMALTYPE, (char *) fc_np);
	if (risnull(CINTTYPE, (char *) &fc_in))
		return 0;

	fc_nres = PGTYPESnumeric_new();
	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	fc_result = PGTYPESnumeric_from_int(fc_in, fc_nres);
	if (fc_result == 0)
		fc_result = PGTYPESnumeric_to_decimal(fc_nres, fc_np);

	PGTYPESnumeric_free(fc_nres);
	return fc_result;
}

int deccvlong(long fc_lng, decimal *fc_np)
{
	numeric    *fc_nres;
	int			fc_result = 1;

	rsetnull(CDECIMALTYPE, (char *) fc_np);
	if (risnull(CLONGTYPE, (char *) &fc_lng))
		return 0;

	fc_nres = PGTYPESnumeric_new();
	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	fc_result = PGTYPESnumeric_from_long(fc_lng, fc_nres);
	if (fc_result == 0)
		fc_result = PGTYPESnumeric_to_decimal(fc_nres, fc_np);

	PGTYPESnumeric_free(fc_nres);
	return fc_result;
}

int decdiv(decimal *fc_n1, decimal *fc_n2, decimal *fc_result)
{
	int			fc_i;

	errno = 0;
	fc_i = fc_deccall3(fc_n1, fc_n2, fc_result, PGTYPESnumeric_div);

	if (fc_i != 0)
		switch (errno)
		{
			case PGTYPES_NUM_DIVIDE_ZERO:
				return ECPG_INFORMIX_DIVIDE_ZERO;
				break;
			case PGTYPES_NUM_OVERFLOW:
				return ECPG_INFORMIX_NUM_OVERFLOW;
				break;
			default:
				return ECPG_INFORMIX_NUM_UNDERFLOW;
				break;
		}

	return 0;
}

int decmul(decimal *fc_n1, decimal *fc_n2, decimal *fc_result)
{
	int			fc_i;

	errno = 0;
	fc_i = fc_deccall3(fc_n1, fc_n2, fc_result, PGTYPESnumeric_mul);

	if (fc_i != 0)
		switch (errno)
		{
			case PGTYPES_NUM_OVERFLOW:
				return ECPG_INFORMIX_NUM_OVERFLOW;
				break;
			default:
				return ECPG_INFORMIX_NUM_UNDERFLOW;
				break;
		}

	return 0;
}

int decsub(decimal *fc_n1, decimal *fc_n2, decimal *fc_result)
{
	int			fc_i;

	errno = 0;
	fc_i = fc_deccall3(fc_n1, fc_n2, fc_result, PGTYPESnumeric_sub);

	if (fc_i != 0)
		switch (errno)
		{
			case PGTYPES_NUM_OVERFLOW:
				return ECPG_INFORMIX_NUM_OVERFLOW;
				break;
			default:
				return ECPG_INFORMIX_NUM_UNDERFLOW;
				break;
		}

	return 0;
}

int dectoasc(decimal *fc_np, char *fc_cp, int fc_len, int fc_right)
{
	char	   *fc_str;
	numeric    *fc_nres;

	rsetnull(CSTRINGTYPE, (char *) fc_cp);
	if (risnull(CDECIMALTYPE, (char *) fc_np))
		return 0;

	fc_nres = PGTYPESnumeric_new();
	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	if (PGTYPESnumeric_from_decimal(fc_np, fc_nres) != 0)
	{
		PGTYPESnumeric_free(fc_nres);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	if (fc_right >= 0)
		fc_str = PGTYPESnumeric_to_asc(fc_nres, fc_right);
	else
		fc_str = PGTYPESnumeric_to_asc(fc_nres, fc_nres->dscale);

	PGTYPESnumeric_free(fc_nres);
	if (!fc_str)
		return -1;

	/*
	 * TODO: 必须在这里处理len，并必要时创建指数表示法
	 */
	if ((int) (strlen(fc_str) + 1) > fc_len)
	{
		if (fc_len > 1)
		{
			fc_cp[0] = '*';
			fc_cp[1] = '\0';
		}
		free(fc_str);
		return -1;
	}
	else
	{
		strcpy(fc_cp, fc_str);
		free(fc_str);
		return 0;
	}
}

int dectodbl(decimal *fc_np, double *fc_dblp)
{
	int			fc_i;
	numeric    *fc_nres = PGTYPESnumeric_new();

	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	if (PGTYPESnumeric_from_decimal(fc_np, fc_nres) != 0)
	{
		PGTYPESnumeric_free(fc_nres);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	fc_i = PGTYPESnumeric_to_double(fc_nres, fc_dblp);
	PGTYPESnumeric_free(fc_nres);

	return fc_i;
}

int dectoint(decimal *fc_np, int *fc_ip)
{
	int			fc_ret;
	numeric    *fc_nres = PGTYPESnumeric_new();

	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	if (PGTYPESnumeric_from_decimal(fc_np, fc_nres) != 0)
	{
		PGTYPESnumeric_free(fc_nres);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	fc_ret = PGTYPESnumeric_to_int(fc_nres, fc_ip);
	PGTYPESnumeric_free(fc_nres);

	if (fc_ret == PGTYPES_NUM_OVERFLOW)
		fc_ret = ECPG_INFORMIX_NUM_OVERFLOW;

	return fc_ret;
}

int dectolong(decimal *fc_np, long *fc_lngp)
{
	int			fc_ret;
	numeric    *fc_nres = PGTYPESnumeric_new();

	if (fc_nres == NULL)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	if (PGTYPESnumeric_from_decimal(fc_np, fc_nres) != 0)
	{
		PGTYPESnumeric_free(fc_nres);
		return ECPG_INFORMIX_OUT_OF_MEMORY;
	}

	fc_ret = PGTYPESnumeric_to_long(fc_nres, fc_lngp);
	PGTYPESnumeric_free(fc_nres);

	if (fc_ret == PGTYPES_NUM_OVERFLOW)
		fc_ret = ECPG_INFORMIX_NUM_OVERFLOW;

	return fc_ret;
}

/* 现在是日期函数 */
int rdatestr(date fc_d, char *fc_str)
{
	char	   *fc_tmp = PGTYPESdate_to_asc(fc_d);

	if (!fc_tmp)
		return ECPG_INFORMIX_DATE_CONVERT;

	/* 移动到用户分配的缓冲区 */
	strcpy(fc_str, fc_tmp);
	free(fc_tmp);

	return 0;
}

/*
*
* 此函数的输入是mmddyyyy，任何非数字字符都可以用作分隔符
*
*/
int rstrdate(const char *fc_str, date * fc_d)
{
	return rdefmtdate(fc_d, "mm/dd/yyyy", fc_str);
}

void rtoday(date * fc_d)
{
	PGTYPESdate_today(fc_d);
}

int rjulmdy(date fc_d, short *fc_mdy)
{
	int			fc_mdy_int[3];

	PGTYPESdate_julmdy(fc_d, fc_mdy_int);
	fc_mdy[0] = (short) fc_mdy_int[0];
	fc_mdy[1] = (short) fc_mdy_int[1];
	fc_mdy[2] = (short) fc_mdy_int[2];
	return 0;
}

int rdefmtdate(date * fc_d, const char *fc_fmt, const char *fc_str)
{
	/* TODO: 处理DBCENTURY环境变量 */
	/* PGSQL函数允许所有世纪 */

	errno = 0;
	if (PGTYPESdate_defmt_asc(fc_d, fc_fmt, fc_str) == 0)
		return 0;

	switch (errno)
	{
		case PGTYPES_DATE_ERR_ENOSHORTDATE:
			return ECPG_INFORMIX_ENOSHORTDATE;
		case PGTYPES_DATE_ERR_EARGS:
		case PGTYPES_DATE_ERR_ENOTDMY:
			return ECPG_INFORMIX_ENOTDMY;
		case PGTYPES_DATE_BAD_DAY:
			return ECPG_INFORMIX_BAD_DAY;
		case PGTYPES_DATE_BAD_MONTH:
			return ECPG_INFORMIX_BAD_MONTH;
		default:
			return ECPG_INFORMIX_BAD_YEAR;
	}
}

int rfmtdate(date fc_d, const char *fc_fmt, char *fc_str)
{
	errno = 0;
	if (PGTYPESdate_fmt_asc(fc_d, fc_fmt, fc_str) == 0)
		return 0;

	if (errno == ENOMEM)
		return ECPG_INFORMIX_OUT_OF_MEMORY;

	return ECPG_INFORMIX_DATE_CONVERT;
}

int rmdyjul(short *fc_mdy, date * fc_d)
{
	int			fc_mdy_int[3];

	fc_mdy_int[0] = fc_mdy[0];
	fc_mdy_int[1] = fc_mdy[1];
	fc_mdy_int[2] = fc_mdy[2];
	PGTYPESdate_mdyjul(fc_mdy_int, fc_d);
	return 0;
}

int rdayofweek(date fc_d)
{
	return PGTYPESdate_dayofweek(fc_d);
}

/* 还有日期时间相关的内容 */

void dtcurrent(timestamp * fc_ts)
{
	PGTYPEStimestamp_current(fc_ts);
}

int dtcvasc(char *fc_str, timestamp * fc_ts)
{
	timestamp	fc_ts_tmp;
	int			fc_i;
	char	  **fc_endptr = &fc_str;

	errno = 0;
	fc_ts_tmp = PGTYPEStimestamp_from_asc(fc_str, fc_endptr);
	fc_i = errno;
	if (fc_i)
		/* TODO: 重写为Informix错误代码 */
		return fc_i;
	if (**fc_endptr)
	{
		/* 结束处存在额外字符 */
		return ECPG_INFORMIX_EXTRA_CHARS;
	}
	/* TODO: 其他Informix错误代码缺失 */

	/* 一切都很好 */
	*fc_ts = fc_ts_tmp;

	return 0;
}

int dtcvfmtasc(char *fc_inbuf, char *fc_fmtstr, timestamp * fc_dtvalue)
{
	return PGTYPEStimestamp_defmt_asc(fc_inbuf, fc_fmtstr, fc_dtvalue);
}

int dtsub(timestamp * fc_ts1, timestamp * fc_ts2, interval * fc_iv)
{
	return PGTYPEStimestamp_sub(fc_ts1, fc_ts2, fc_iv);
}

int dttoasc(timestamp * fc_ts, char *fc_output)
{
	char	   *fc_asctime = PGTYPEStimestamp_to_asc(*fc_ts);

	strcpy(fc_output, fc_asctime);
	free(fc_asctime);
	return 0;
}

int dttofmtasc(timestamp * fc_ts, char *fc_output, int fc_str_len, char *fc_fmtstr)
{
	return PGTYPEStimestamp_fmt_asc(fc_ts, fc_output, fc_str_len, fc_fmtstr);
}

int intoasc(interval * fc_i, char *fc_str)
{
	char	   *fc_tmp;

	errno = 0;
	fc_tmp = PGTYPESinterval_to_asc(fc_i);

	if (!fc_tmp)
		return -errno;

	strcpy(fc_str, fc_tmp);
	free(fc_tmp);
	return 0;
}

static struct
{
	long		val;
	int			maxdigits;
	int			digits;
	int			remaining;
	char		sign;
	char	   *val_string;
}			value;

/**
 * 初始化结构，保持长值的不同形式
 */
static int fc_initValue(long fc_lng_val)
{
	int			fc_i,
				fc_j;
	long		fc_l,
				fc_dig;

	/* 设置一些明显的东西 */
	value.val = fc_lng_val >= 0 ? fc_lng_val : fc_lng_val * (-1);
	value.sign = fc_lng_val >= 0 ? '+' : '-';
	value.maxdigits = log10(2) * (8 * sizeof(long) - 1);

	/* 确定数字的位数 */
	fc_i = 0;
	fc_l = 1;
	do
	{
		fc_i++;
		fc_l *= 10;
	}
	while ((fc_l - 1) < value.val && fc_l <= LONG_MAX / 10);

	if (fc_l <= LONG_MAX / 10)
	{
		value.digits = fc_i;
		fc_l /= 10;
	}
	else
		value.digits = fc_i + 1;

	value.remaining = value.digits;

	/* 将长整型转换为字符串 */
	if ((value.val_string = (char *) malloc(value.digits + 1)) == NULL)
		return -1;
	fc_dig = value.val;
	for (fc_i = value.digits, fc_j = 0; fc_i > 0; fc_i--, fc_j++)
	{
		value.val_string[fc_j] = fc_dig / fc_l + '0';
		fc_dig = fc_dig % fc_l;
		fc_l /= 10;
	}
	value.val_string[value.digits] = '\0';
	return 0;
}

/* 返回某个字符串中最右边点的位置 */
static int fc_getRightMostDot(const char *fc_str)
{
	size_t		fc_len = strlen(fc_str);
	int			fc_i,
				fc_j;

	fc_j = 0;
	for (fc_i = fc_len - 1; fc_i >= 0; fc_i--)
	{
		if (fc_str[fc_i] == '.')
			return fc_len - fc_j - 1;
		fc_j++;
	}
	return -1;
}

/* 最后是一些杂项函数 */
int rfmtlong(long fc_lng_val, const char *fc_fmt, char *fc_outbuf)
{
	size_t		fc_fmt_len = strlen(fc_fmt);
	size_t		fc_temp_len;
	int			fc_i,
				fc_j,				/* 在临时位置 */
				fc_k,
				fc_dotpos;
	int			fc_leftalign = 0,
				fc_blank = 0,
				fc_sign = 0,
				fc_entitydone = 0,
				fc_signdone = 0,
				fc_brackets_ok = 0;
	char	   *fc_temp;
	char		fc_tmp[2] = " ";
	char		fc_lastfmt = ' ',
				fc_fmtchar = ' ';

	fc_temp = (char *) malloc(fc_fmt_len + 1);
	if (!fc_temp)
	{
		errno = ENOMEM;
		return -1;
	}

	/* 将有关长整型的所有信息放入结构中 */
	if (fc_initValue(fc_lng_val) == -1)
	{
		free(fc_temp);
		errno = ENOMEM;
		return -1;
	}

	/* '<'是唯一的格式，我们必须左对齐 */
	if (strchr(fc_fmt, (int) '<'))
		fc_leftalign = 1;

	/* '('需要')' */
	if (strchr(fc_fmt, (int) '(') && strchr(fc_fmt, (int) ')'))
		fc_brackets_ok = 1;

	/* 获得格式字符串中最右边点的位置 */
	/* 并用'0'填充临时字符串到那里。 */
	fc_dotpos = fc_getRightMostDot(fc_fmt);

	/* 开始解析格式字符串 */
	fc_temp[0] = '\0';
	fc_k = value.digits - 1;		/* 在value_string中的位置 */
	for (fc_i = fc_fmt_len - 1, fc_j = 0; fc_i >= 0; fc_i--, fc_j++)
	{
		/* 确定我们在value_string中的位置 */
		if (fc_k < 0)
		{
			fc_blank = 1;
			if (fc_k == -1)
				fc_sign = 1;
			if (fc_leftalign)
			{
				/* 这里不能使用strncat(,,0)，Solaris会崩溃 */
				if (fc_sign)
					if (fc_signdone)
					{
						fc_temp[fc_j] = '\0';
						break;
					}
			}
		}
		/* 如果我们在最右边的点的右侧，打印'0' */
		if (fc_dotpos >= 0 && fc_dotpos <= fc_i)
		{
			if (fc_dotpos < fc_i)
			{
				if (fc_fmt[fc_i] == ')')
					fc_tmp[0] = value.sign == '-' ? ')' : ' ';
				else
					fc_tmp[0] = '0';
			}
			else
				fc_tmp[0] = '.';
			strcat(fc_temp, fc_tmp);
			continue;
		}
		/* ','需要特别关注，如果它在空白区域 */
		if (fc_blank && fc_fmt[fc_i] == ',')
			fc_fmtchar = fc_lastfmt;
		else
			fc_fmtchar = fc_fmt[fc_i];
		/* 等待符号 */
		if (fc_k < 0 && fc_leftalign && fc_sign && !fc_signdone && fc_fmtchar != '+' && fc_fmtchar != '-')
			continue;
		/* 分析这个格式字符 */
		switch (fc_fmtchar)
		{
			case ',':
				fc_tmp[0] = ',';
				fc_k++;
				break;
			case '*':
				if (fc_blank)
					fc_tmp[0] = '*';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case '&':
				if (fc_blank)
					fc_tmp[0] = '0';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case '#':
				if (fc_blank)
					fc_tmp[0] = ' ';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case '-':
				if (fc_sign && value.sign == '-' && !fc_signdone)
				{
					fc_tmp[0] = '-';
					fc_signdone = 1;
				}
				else if (fc_blank)
					fc_tmp[0] = ' ';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case '+':
				if (fc_sign && !fc_signdone)
				{
					fc_tmp[0] = value.sign;
					fc_signdone = 1;
				}
				else if (fc_blank)
					fc_tmp[0] = ' ';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case '(':
				if (fc_sign && fc_brackets_ok && value.sign == '-')
					fc_tmp[0] = '(';
				else if (fc_blank)
					fc_tmp[0] = ' ';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case ')':
				if (fc_brackets_ok && value.sign == '-')
					fc_tmp[0] = ')';
				else
					fc_tmp[0] = ' ';
				break;
			case '$':
				if (fc_blank && !fc_entitydone)
				{
					fc_tmp[0] = '$';
					fc_entitydone = 1;
				}
				else if (fc_blank)
					fc_tmp[0] = ' ';
				else
					fc_tmp[0] = value.val_string[fc_k];
				break;
			case '<':
				fc_tmp[0] = value.val_string[fc_k];
				break;
			default:
				fc_tmp[0] = fc_fmt[fc_i];
		}
		strcat(fc_temp, fc_tmp);
		fc_lastfmt = fc_fmt[fc_i];
		fc_k--;
	}
	/* 安全网 */
	fc_temp[fc_fmt_len] = '\0';

	/* 反转临时字符串并放入输出缓冲区 */
	fc_temp_len = strlen(fc_temp);
	fc_outbuf[0] = '\0';
	for (fc_i = fc_temp_len - 1; fc_i >= 0; fc_i--)
	{
		fc_tmp[0] = fc_temp[fc_i];
		strcat(fc_outbuf, fc_tmp);
	}
	fc_outbuf[fc_temp_len] = '\0';

	/* 清理 */
	free(fc_temp);
	free(value.val_string);

	return 0;
}

void rupshift(char *fc_str)
{
	for (; *fc_str != '\0'; fc_str++)
		if (islower((unsigned char) *fc_str))
			*fc_str = toupper((unsigned char) *fc_str);
}

int byleng(char *fc_str, int fc_len)
{
	for (fc_len--; fc_str[fc_len] && fc_str[fc_len] == ' '; fc_len--);
	return (fc_len + 1);
}

void ldchar(char *fc_src, int fc_len, char *fc_dest)
{
	int			fc_dlen = byleng(fc_src, fc_len);

	memmove(fc_dest, fc_src, fc_dlen);
	fc_dest[fc_dlen] = '\0';
}

int rgetmsg(int fc_msgnum, char *fc_s, int fc_maxsize)
{
	(void) fc_msgnum;				/* 让编译器安静 */
	(void) fc_s;					/* 让编译器安静 */
	(void) fc_maxsize;				/* 让编译器安静 */
	return 0;
}

int rtypalign(int fc_offset, int fc_type)
{
	(void) fc_offset;				/* 让编译器安静 */
	(void) fc_type;				/* 让编译器安静 */
	return 0;
}

int rtypmsize(int fc_type, int fc_len)
{
	(void) fc_type;				/* 让编译器安静 */
	(void) fc_len;					/* 让编译器安静 */
	return 0;
}

int rtypwidth(int fc_sqltype, int fc_sqllen)
{
	(void) fc_sqltype;				/* 让编译器安静 */
	(void) fc_sqllen;				/* 让编译器安静 */
	return 0;
}

void ECPG_informix_set_var(int fc_number, void *fc_pointer, int fc_lineno)
{
	ECPGset_var(fc_number, fc_pointer, fc_lineno);
}

void * ECPG_informix_get_var(int fc_number)
{
	return ECPGget_var(fc_number);
}

void ECPG_informix_reset_sqlca(void)
{
	struct sqlca_t *fc_sqlca = ECPGget_sqlca();

	if (fc_sqlca == NULL)
		return;

	memcpy((char *) fc_sqlca, (char *) &sqlca_init, sizeof(struct sqlca_t));
}

int rsetnull(int fc_t, char *fc_ptr)
{
	ECPGset_noind_null(fc_t, fc_ptr);
	return 0;
}

int risnull(int fc_t, const char *fc_ptr)
{
	return ECPGis_noind_null(fc_t, fc_ptr);
}
